package tool;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;

import java.awt.event.MouseListener;
import java.util.HashMap;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

/* The main idea here is to create the Tree of UI elements of captured GUI java classes
 * GUI components in Java are organized in categories that basically present a tree.
 * The tree is generated by traversing all the components and saving each node in a tree (ComponentTreeModel.java)
 * The second task is to regenerate the GUI (regenerateGUI() function), by traversing the tree model
 * and add each component from the tree to the South Panel
 * Then, we add mouse listeners to each of these components and a righ-click menu "Inspect element"
 * so, we capture the clicked component on the UI and map the corresponding object that is 
 * in the Aspect hashMap, and finally show visually in a JTable
 */

public class InspectElement {

	public JFrame frame;
	public JTree tree;
	public JButton btnShowUI;
	public JTable showInfoTable;
	public JScrollPane tableScrollPane;
	public JScrollPane pnlSouthScrollPane;
	public static DefaultTableModel model;
	public String[] columns = {};
	public String[][] rows = {};

	public JPanel pnlNorth;
	public JPanel pnlSouth;
	public JPanel pnlNorthWest;
	public JPanel pnlCenter;
	public JPanel pnlNorthEast;
	public JPanel pnlNorthCenter;

	private JMenuBar mb = new JMenuBar(); // Menubar
	private JMenu mnuFile = new JMenu("File"); // File Entry on Menu bar
	private JMenuItem mnuItemQuit = new JMenuItem("Quit"); // Quit sub item
	private JMenu mnuHelp = new JMenu("Help"); // Help Menu entry
	private JMenuItem mnuItemAbout = new JMenuItem("About"); // About Entry

	public static HashMap<Integer, Object> pixelShapes = new HashMap<Integer, Object>();
	public static JComponent rootCmp;
	public MouseListener myListener;
	
	public InspectElement(JComponent cmp) {
		makeUI(cmp);
	}

	@SuppressWarnings("static-access")
	public void makeUI(JComponent cmp) {

		// Main window which keeps the GUI design of our tool

		mnuFile.add(mnuItemQuit);
		mnuHelp.add(mnuItemAbout);
		mb.add(mnuFile);
		mb.add(mnuHelp);

		model = new DefaultTableModel(13, 2);
		model.fireTableStructureChanged();
		showInfoTable = new JTable(model);
		showInfoTable.setAutoResizeMode(showInfoTable.AUTO_RESIZE_ALL_COLUMNS);
		tableScrollPane = new JScrollPane(showInfoTable);
		tableScrollPane
				.setHorizontalScrollBarPolicy(tableScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		tableScrollPane
				.setVerticalScrollBarPolicy(tableScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		//tableScrollPane.setPreferredSize(new Dimension(200, 220));

		btnShowUI = new JButton(regenerateGUI);
		pnlNorthWest = new JPanel();

		pnlNorthWest.setName("Tree of UI Components");
		pnlNorthWest.setPreferredSize(new Dimension(600, 220));
		pnlNorthWest.setBorder(new LineBorder(Color.black, 1));
		BoxLayout boxLayoutNW = new BoxLayout(pnlNorthWest, BoxLayout.Y_AXIS);
		pnlNorthWest.setLayout(boxLayoutNW);
		pnlNorthWest.setBorder(new TitledBorder("Tree of UI Elements"));

		pnlNorth = new JPanel();
		pnlNorth.setPreferredSize(new Dimension(550, 200));
		pnlNorth.setBorder(new LineBorder(Color.black, 1));
		BoxLayout boxLayout = new BoxLayout(pnlNorth, BoxLayout.X_AXIS);
		pnlNorth.setLayout(boxLayout);
		pnlNorth.add(Box.createHorizontalGlue());

		pnlNorth.add(pnlNorthWest);

		pnlSouth = new JPanel();
		pnlSouth.setBackground(Color.white);
		pnlSouth.setName("Regenerated GUI application");
		pnlSouth.setPreferredSize(new Dimension(550, 220));
		pnlSouth.add(tableScrollPane);
		// pnlSouth.setBorder(new LineBorder(Color.black, 1));
		pnlSouthScrollPane = new JScrollPane(pnlSouth);
		pnlSouthScrollPane.setPreferredSize(new Dimension(550, 220));
		pnlSouthScrollPane
				.setHorizontalScrollBarPolicy(pnlSouthScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		pnlSouthScrollPane
				.setVerticalScrollBarPolicy(pnlSouthScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		pnlSouthScrollPane.setAutoscrolls(true);
		JSplitPane hpane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, pnlNorth,
				pnlSouthScrollPane);
		pnlSouth.setBorder(new TitledBorder("Regenerated GUI"));
		generateTree(cmp);

		frame = new JFrame();
		// frame.setSize(400, 300);
		frame.setJMenuBar(mb);
		frame.add(hpane2);

		frame.setLocationRelativeTo(null);
		frame.pack();
		frame.setVisible(true);
		frame.setTitle("GUI Explorer - Frame Inspected: " + Aspect.frameName);
	}

	// regenerate the GUI from traversing the Tree Model, getting the objects
	// and add each object to the South Panel
	public void regenerateGUI(JPanel pnl) {
		TreePath[] paths = tree.getSelectionPaths();

		if (paths != null) {
			for (TreePath d : paths) {
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) d
						.getLastPathComponent();
				JComponent comp = (JComponent) node.getUserObject();
				comp.setBorder(new LineBorder(Color.black));
				pnl.add(comp);
				pnl.validate();
				pnl.repaint();
			}
		} else {
			JOptionPane.showMessageDialog(null,
					"Please, select the root node on the Tree",
					"Empty Selection", JOptionPane.INFORMATION_MESSAGE);
		}
	}

	// function which creates the TREE of UI elements
	// as input takes any UI element (button, panel, txtField etc) except JFrame
	public void generateTree(Component cmp) {

		// find the root component of the inputed component, since the
		// ComponentTreeModel requires
		// the root component in order to generate the tree of UI elements
		JComponent component = (JComponent) cmp;
		JComponent root = SwingUtilities.getRootPane(component);
		if (root == null) {
			JComponent parent = component;
			while (parent instanceof JComponent && parent != null) {
				root = parent;
				parent = (JComponent) parent.getParent();
			}
		}

		// ComponentTreeModel function creates the tree of UI elements
		tree = new JTree(new ComponentTreeModel(root));

		for (int i = 0; i < tree.getRowCount(); i++) {
			tree.expandRow(i);
		}

		rootCmp = root;
		getComponentPixels(rootCmp);
		
		// show the tree in a scrollPane
		JScrollPane scrollPane = new JScrollPane(tree);
		scrollPane.setPreferredSize(new Dimension(850, 180));
		pnlNorthWest.add(scrollPane);

	}

	public void getPixels(Component cmp) {
		Point p = cmp.getLocation();
		SwingUtilities.convertPointToScreen(p, cmp.getParent());
		
		int w = cmp.getBounds().width + p.x;
		int h = cmp.getBounds().height + p.y;
		
		for (int i = p.x; i <= w; i++) {
			for (int j = p.y; j <= h; j++) {
				pixelShapes.put(("" + i + j).hashCode(), cmp);
			}
		}
	}

	//recursively get Pixels for each Component
	public void getComponentPixels(Component cmp) {
		Container cnt = (Container) cmp;
		for(Component child : cnt.getComponents()){
			getPixels(child);
			getComponentPixels(child);
		}
	}
	
	// recursive function which adds a right-click menu (PopClickListener) to
	// all UI elements
	public void getChildComp(Component comp) {
		Container component = (Container) comp;
		for (Component child : component.getComponents()) {
			child.addMouseListener(new PopClickListener());
			getChildComp(child);
		}
	}

	@SuppressWarnings("serial")
	Action regenerateGUI = new AbstractAction("Regenerate GUI") {

		public void actionPerformed(ActionEvent e) {
			regenerateGUI(pnlSouth);

			pnlSouth.repaint();

			// add mouseListeners on each component regenerated
			// so, we can Inspect them later..
			getChildComp(pnlSouth);

			pnlSouth.repaint();
		}
	};
}